package com.example.blueconn.manager;

import android.bluetooth.BluetoothGatt;
import android.util.Log;

import androidx.lifecycle.MutableLiveData;

import com.clj.fastble.BleManager;
import com.clj.fastble.callback.BleGattCallback;
import com.clj.fastble.callback.BleMtuChangedCallback;
import com.clj.fastble.callback.BleNotifyCallback;
import com.clj.fastble.callback.BleReadCallback;
import com.clj.fastble.callback.BleScanCallback;
import com.clj.fastble.callback.BleWriteCallback;
import com.clj.fastble.data.BleDevice;
import com.clj.fastble.exception.BleException;
import com.example.blueconn.Constant;
import com.example.blueconn.utils.DataUtils;

import java.util.List;

/**
 * Created by zhudongao
 * Desc
 * Date 3/23/21
 */

public class FastBleManager {

    private static final String TAG = "FastBleManager";

    private static final FastBleManager INSTANCE = new FastBleManager();

    private BleDevice blBleDevice;
    private MutableLiveData<BleDevice> bleDeviceObservable = new MutableLiveData<>();

    private final StringBuilder stringBuilder = new StringBuilder();

    private final MutableLiveData<String> scanTipMsg = new MutableLiveData<>();
    public static final MutableLiveData<Integer> connTipMsg = new MutableLiveData<>();
    public static final MutableLiveData<Boolean> recon = new MutableLiveData<>();

    private FastBleManager() {

    }

    public static FastBleManager getInstance() {
        return INSTANCE;
    }


    public MutableLiveData<BleDevice> getBleDeviceObservable() {
        return bleDeviceObservable;
    }

    public void scanBle() {
        if (BleManager.getInstance().isBlueEnable()) {
            BleManager.getInstance().enableBluetooth();
        }
        BleManager.getInstance().scan(new BleScanCallback() {
            @Override
            public void onScanStarted(boolean success) {
                Log.i(TAG, "扫描开始！");
                scanTipMsg.postValue("开始扫描...");
            }

            @Override
            public void onScanning(BleDevice bleDevice) {
                scanTipMsg.postValue("扫描中...");
                bleDeviceObservable.postValue(bleDevice);
                Log.i(TAG, "扫描中 name: " + bleDevice.getName() + "; mac: " + bleDevice.getMac());
            }

            @Override
            public void onScanFinished(List<BleDevice> scanResultList) {
                Log.i(TAG, "扫描结束！");
                scanTipMsg.postValue("扫描结束!");
                for (BleDevice devices : scanResultList) {
                    Log.i(TAG, "name: " + devices.getName() + "; mac: " + devices.getMac());
                }
            }
        });
    }


    public void connect(String mac) {
        if (BleManager.getInstance().isBlueEnable()) {
            BleManager.getInstance().enableBluetooth();
        }
        Log.i(TAG, "发起连接 mac：" + mac);
        BleManager.getInstance().connect(mac, new BleGattCallback() {
            @Override
            public void onStartConnect() {
                connTipMsg.postValue(1);
            }

            @Override
            public void onConnectFail(BleDevice bleDevice, BleException exception) {
                Log.e(TAG, "连接失败！");
                connTipMsg.postValue(2);
            }

            @Override
            public void onConnectSuccess(BleDevice bleDevice, BluetoothGatt gatt, int status) {
                Log.i(TAG, "连接成功！");
                connTipMsg.postValue(3);
                blBleDevice = bleDevice;
                startNotify();
            }

            @Override
            public void onDisConnected(boolean isActiveDisConnected, BleDevice bleDevice, BluetoothGatt gatt, int status) {
                connTipMsg.postValue(4);
            }
        });
    }

    public void writeData(byte[] data) {
        Log.w(TAG, "写入数据 data：" + DataUtils.bytesToHex(data));
        BleManager.getInstance().write(
                blBleDevice,
                Constant.UUID_SERVICE,
                Constant.UUID_CHARACTER,
                data,
                new BleWriteCallback() {
                    @Override
                    public void onWriteSuccess(int current, int total, byte[] justWrite) {
                        Log.w(TAG, "total: " + total + " , write bluetooth data: " + DataUtils.bytesToHex(justWrite));
//                        startRead();
                    }

                    @Override
                    public void onWriteFailure(BleException exception) {
                        Log.e(TAG, "onWriteFailure: " + exception.getDescription());
                    }
                });
    }

    public void startRead() {
        BleManager.getInstance().read(
                blBleDevice,
                Constant.UUID_SERVICE,
                Constant.UUID_CHARACTER,
                new BleReadCallback() {
                    @Override
                    public void onReadSuccess(byte[] data) {
                        Log.w(TAG, "read bluetooth data: " + DataUtils.bytesToHex(data));

                        stringBuilder.setLength(0);
                        stringBuilder.append(DataUtils.bytesToHex(data));
                        DataMgr.getInstance().postRawData(stringBuilder.toString());
                    }

                    @Override
                    public void onReadFailure(BleException exception) {
                        Log.e(TAG, "onReadFailure: " + exception.getDescription());
                    }
                });
    }

    public void startNotify() {
        BleManager.getInstance().notify(
                blBleDevice,
                Constant.UUID_SERVICE,
                Constant.UUID_CHARACTER,
                new BleNotifyCallback() {
                    @Override
                    public void onNotifySuccess() {
                        // 打开通知操作成功
                        Log.i(TAG, "notify success");
                    }

                    @Override
                    public void onNotifyFailure(BleException exception) {
                        // 打开通知操作失败
                        Log.i(TAG, "notify failed");
                    }

                    @Override
                    public void onCharacteristicChanged(byte[] data) {
                        Log.i(TAG, "notify received : " + DataUtils.bytesToHex(data));
                        DataMgr.getInstance().postRawData(DataUtils.bytesToHex(data));
                    }
                });
    }

    public void setMTU(int mtu) {
        if (blBleDevice == null) {
            return;
        }
        BleManager.getInstance().setMtu(blBleDevice, mtu, new BleMtuChangedCallback() {
            @Override
            public void onSetMTUFailure(BleException exception) {
                Log.i(TAG, "onSetMTUFailure: " + exception);
            }

            @Override
            public void onMtuChanged(int mtu) {
                Log.i(TAG, "mtu set success : " + mtu);
            }
        });
    }

    public MutableLiveData<String> getScanTipMsg() {
        return scanTipMsg;
    }
}
